// get 和 set 是 类（Class） 或 对象（Object） 中的特殊方法，用于定义属性的 读取（getter） 和 写入（setter） 行为。
// 它们可以让一个属性像普通变量一样被访问和修改

// GUI  调试面板库
// 辅助类：THREE.Color 不能直接被 dat.GUI 修改，所以需要转换成 HEX 字符串（#ffffff 格式）

/// 环境光
// intensity--强度，color--颜色
import { useEffect } from 'react';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import * as dat from 'dat.gui'; // 导入 dat.GUI

function SimpleCubeWithLight() {
  useEffect(() => {
    // ---------------初始化场景、相机、渲染器
    const scene = new THREE.Scene();
    scene.background = new THREE.Color('white');

    const fov = 45;
    const aspect = 2; // canvas 的默认宽高 300:150
    const near = 0.1;
    const far = 100;
    const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
    camera.position.set(0, 10, 10);

    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 轨道控制器，实现围绕观察点旋转相机
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.target.set(0, 5, 5); // 观察点
    controls.update();

    // -----------------------物体
    // 二维平面底座
    // 1、设置纹理
    const planeSize = 40;
    const loader = new THREE.TextureLoader();
    const texture = loader.load('/masaike.png');
    texture.wrapS = THREE.RepeatWrapping; // 纹理重复-水平包裹
    texture.wrapT = THREE.RepeatWrapping;
    texture.magFilter = THREE.NearestFilter;
    const repeats = planeSize / 2;
    texture.repeat.set(repeats, repeats);
    const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
    const planeMat = new THREE.MeshPhongMaterial({
      map: texture,
      side: THREE.DoubleSide,
    });
    const mesh = new THREE.Mesh(planeGeo, planeMat);
    mesh.rotation.x = Math.PI * -0.5;
    scene.add(mesh);
    // 几何体
    const cubeSize = 3;
    const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
    const cubeMat = new THREE.MeshPhongMaterial({ color: '#8AC' });
    const mesh2 = new THREE.Mesh(cubeGeo, cubeMat);
    mesh2.position.set(cubeSize + 2, cubeSize / 2, 0);
    scene.add(mesh2);

    const sphereRadius = 1.5;
    const sphereWidthDivisions = 32;
    const sphereHeightDivisions = 16;
    const sphereGeo = new THREE.SphereGeometry(
      sphereRadius,
      sphereWidthDivisions,
      sphereHeightDivisions
    );
    const sphereMat = new THREE.MeshPhongMaterial({ color: '#CA8' });
    const mesh3 = new THREE.Mesh(sphereGeo, sphereMat);
    mesh3.position.set(-sphereRadius - 4, sphereRadius, 0);
    scene.add(mesh3);

    // ----------------------------光源
    // 1创建环境光AmbientLight
    const color = 0xffffff;
    const intensity = 1;
    const light = new THREE.AmbientLight(color, intensity);
    scene.add(light);
    // 2创建辅助类，帮助gui实现修改颜色
    class ColorGUIHelper {
      constructor(object, prop) {
        this.object = object;
        this.prop = prop;
      }
      // 当读取value时，返回this.prop (light.color) 的 HEX 字符串格式（如 "#ffffff")
      get value() {
        return `#${this.object[this.prop].getHexString()}`;
      }
      // 当修改value时，将 HEX 字符串（如 "#ff0000"）设置给 this.prop (light.color)
      set value(hexString) {
        this.object[this.prop].set(hexString);
      }
    }
    const gui = new dat.GUI();
    gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
    // new ColorGUIHelper(light, 'color')创建一个辅助类对象，对value进行读写
    // .name('color') 在 UI 上显示为 color
    gui.add(light, 'intensity', 0, 2, 0.01);
    //light：目标对象。
    //'intensity'：控制 light.intensity。
    //0, 2：取值范围（最小 0，最大 2）。
    //0.01：步长（每次调整增减 0.01）。

    // --------------------------------渲染
    function animate() {
      requestAnimationFrame(animate);
      renderer.render(scene, camera);
    }
    animate();

    // 清理函数
    return () => {
      document.body.removeChild(renderer.domElement);
      gui.destroy(); // 由于useEffect 执行两次，所以在组件卸载时销毁 GUI
    };
  }, []);

  return <div />;
}

export default SimpleCubeWithLight;
